//AbstractAdvancedModel.h
//Created 27/01/14
//Created By Daniel Bowler
//
//Advanced models (those not handled by other means - eg the Ocean wave) will inherit
//from this class which provides basic functionality and overridable functions. By doing
//so, the advanced model should work seemlessly(sp?) with the GraphicsInterface. Therefore,
//the scene programmer will not have a harder time dealing with the advanced model. 

#pragma once 

//Include D3D resource headers, math helper and XNA collisions (aabb). 
#include "d3dUtil.h"
#include "xnacollision.h"
#include "MathHelper.h"
//Used in the Render function - we include here so the subclassses dont need
//to include. 
#include "VirtualCamera.h"
#include "DirecLightShadowMapData.h"
#include "SSAOData.h"

//Matrix that converts from NDC space [-1, 1] to tex space [0,1]
const XMMATRIX TO_TEX_SPACE(
	0.5f, 0.0f, 0.0f, 0.0f, 
	0.0f, -0.5f, 0.0f, 0.0f,
	0.0f, 0.0f, 1.0f, 0.0f, 
	0.5f, 0.5f, 0.0f, 1.0f);

class AbstractAdvancedModel
{
	//Friend so the GraphicsInterface can access private stuff 
	//- eg, the AABB (for frustum culling)
	friend class GraphicsInterface;
public:
	//Standard constructor - does nothing apart from initing 
	//the AABB - Called BEFORE subclasses constructor. 
	AbstractAdvancedModel();
	//Virtual destrouctor - This class is a pure abstract class too. 
	virtual ~AbstractAdvancedModel() = 0;

public:
	//Sets the world matrix data. 
	void SetWorldPosition(XMFLOAT3 pos);
	void SetWorldRotation(XMFLOAT3 rot);
	//Note: Make sure that the x, y and z scale factors are the same. Otherwise, 
	//frustum culling causes a crash. I may look in to fixing this at somepoint. 
	void SetWorldScale(XMFLOAT3 scale);
	void SetWorldMatrix(XMFLOAT3 pos, XMFLOAT3 rot, XMFLOAT3 scale);
	//Gets the world matrix data
	XMFLOAT3 GetWorldPosition(){return position;};
	XMFLOAT3 GetWorldRotation(){return rotation;};
	XMFLOAT3 GetWorldScale(){return scaling;};

	//Returns the local space AABB
	XNA::AxisAlignedBox GetAABBL(){return aabbL;};

	//Returns AABB in world space
	XNA::AxisAlignedBox CalculateWorldSpaceAABB();

protected:
	//Private render function - the graphics interface will call this function
	//(rather than the scene programmer)
	//
	//Note: No default functionality, must override.
	virtual void Render(bool isZPrePass, bool isOpaquePass, bool isShadowPass, //Flags telling us what pass it is. 
		VirtualCamera* playerCamera,										   //Player camera - passed from GraphicsInterface
		DirecLightShadowMapData* shadowMap,									   //Single shadow map - passed from GraphicsInterface. 
		SSAOData* ssaoMap,												       //SSAO Map.
		ID3D11ShaderResourceView* envMap,									   //Environment map. 
		ID3D11ShaderResourceView* llb,                                         //Light list buffer - gloabl set of lights. 
		ID3D11ShaderResourceView* llibO, ID3D11ShaderResourceView* llsebO,     //Opaque Tile Based Forward buffers. 
		ID3D11ShaderResourceView* llibT, ID3D11ShaderResourceView* llsebT,     //Transparant pass. 
		DirectionalLight* dLightArr, unsigned dLightCount,					   //Directional lights and light count. 
		XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange,					       //Hemispherical ambient lighting data. 
		CXMMATRIX &view, CXMMATRIX &proj,									   //Cameras view/proj or the shadow maps view/proj depending on the pass. 
		ID3D11DeviceContext* context) = 0;									   //Context used to draw 

	//This function is called by the Graphics Interface when an advanced model
	//has been added to the batch. The idea being that if an advanced model
	//has other models to add, it can do so by overriding this function. 
	//
	//default does nothing...
	virtual void OnBatchAdd(GraphicsInterface* sharedGraphicsInterface);

protected:	
	//flag set to true after the model has been inited and therefore
	//free to be rendered - The subclass is responsable for setting this to 
	//true (Dont forget it)
	bool isInit;

	//Flag - when true, the GraphicsInterface will NOT do frustum culling (you do it in Render). - Default
	//to false. 
	bool subclassManagesFrustumCulling;

	//AABB that covers the entire model 
	XNA::AxisAlignedBox aabbL;
	//System copy of verticies (positions) - used to generate 
	//the AABB. 
	std::vector<XMFLOAT3>sysCopyVerts;

	//World matrix. 
	XMFLOAT4X4 worldMatrix;
	XMFLOAT3 position;
	XMFLOAT3 scaling;
	XMFLOAT3 rotation;

protected:
	//This function provides default functionality (Optional to override)
	//to generate the aabbL from sysCopyVerts
	void GenerateAABB();
	
	//Default functionality to generate the worldMatrix
	void CreateWorldMatrix();
};